#include "methodeditor.h"
#include "ui_methodeditor.h"

#include "uml/class/classmethod.h"
#include "uml/class/umlclassitem.h"

MethodEditor::MethodEditor(UmlClassItem *classItem, ClassMethod *classMethod) :
    ui(new Ui::MethodEditor),
    _classItem(classItem)
{
    ui->setupUi(this);

    this->_meth = 0;

    if (!classMethod) {
        ClassMethod *meth = new ClassMethod();
        meth->setClassItem(classItem);
        this->setMeth(meth);
    } else {
        this->setMeth(classMethod);
    }

    this->_previewHighlighter = new UmlMethodHighlighter(this->ui->textEditPreview->document(), this->_classItem->project()->dataTypes());

    QWidget::setAttribute(Qt::WA_DeleteOnClose);

    // save and close
    QObject::connect(this->ui->pushButtonSave, SIGNAL(clicked()), this, SLOT(save()));
    QObject::connect(this->ui->pushButtonCancel, SIGNAL(clicked()), this, SLOT(close()));

    // name
    QObject::connect(this->ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(setName(QString)));
    QObject::connect(this->ui->nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(updatePreview()));

    // visibility
    QObject::connect(this->ui->visibilityComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setVisibility(int)));
    QObject::connect(this->ui->visibilityComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));

    // return type
    QObject::connect(this->ui->returnTypeComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(setReturnType(QString)));
    QObject::connect(this->ui->returnTypeComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(updatePreview()));

    // is abstract
    QObject::connect(this->ui->isAbstractCheckBox, SIGNAL(toggled(bool)), this, SLOT(setIsAbstract(bool)));
    QObject::connect(this->ui->isAbstractCheckBox, SIGNAL(toggled(bool)), this, SLOT(updatePreview()));

    // arguments
    QObject::connect(this->ui->tableViewArguments, SIGNAL(pressed(QModelIndex)), this, SLOT(updatePreview()));
    QObject::connect(this->ui->toolButtonArgAdd, SIGNAL(clicked()), this, SLOT(addArg()));
    QObject::connect(this->ui->toolButtonArgAdd, SIGNAL(clicked()), this, SLOT(updatePreview()));
    QObject::connect(this->ui->toolButtonArgRemove, SIGNAL(clicked()), this, SLOT(removeArg()));
    QObject::connect(this->ui->toolButtonArgRemove, SIGNAL(clicked()), this, SLOT(updatePreview()));
    QObject::connect(this->ui->toolButtonUp, SIGNAL(clicked()), this, SLOT(moveArgUp()));
    QObject::connect(this->ui->toolButtonUp, SIGNAL(clicked()), this, SLOT(updatePreview()));
    QObject::connect(this->ui->toolButtonDown, SIGNAL(clicked()), this, SLOT(moveArgDown()));
    QObject::connect(this->ui->toolButtonDown, SIGNAL(clicked()), this, SLOT(updatePreview()));

    QObject::connect(this->ui->tableViewArguments, SIGNAL(clicked(QModelIndex)), this, SLOT(updatePreview()));
}

MethodEditor::~MethodEditor()
{
    delete ui;
}

void MethodEditor::setMeth(ClassMethod *meth)
{
    this->_meth = meth;

    this->ui->isAbstractCheckBox->setChecked(meth->isAbstract());

    this->ui->nameLineEdit->setText(this->_meth->name());
    this->ui->visibilityComboBox->setSelectedVisibility(this->_meth->visibilityToString());

    this->ui->tableViewArguments->setModel(this->_meth);
    this->ui->tableViewArguments->setItemDelegate(this->_meth);

    int index = this->_classItem->project()->dataTypes()->indexByLabel(this->_meth->returnType());
    this->ui->returnTypeComboBox->setCurrentIndex(index);
}

void MethodEditor::setClassItem(UmlClassItem *classItem)
{
    this->_classItem = classItem;
}

void MethodEditor::setDatatypes(DatatypeDictionary *datatypes)
{
    this->_datatypes = datatypes;
    this->ui->returnTypeComboBox->setModel(this->_datatypes);

    if (this->_meth) {
        int index = this->_datatypes->indexByLabel(this->_meth->returnType());

        if (index >= 0) {
            this->ui->returnTypeComboBox->setCurrentIndex(index);
        }
    }
}

void MethodEditor::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MethodEditor::save()
{
    this->_meth->setText(this->ui->nameLineEdit->text());
    this->_meth->setIsAbstract(this->ui->isAbstractCheckBox->isChecked());
    this->_meth->setReturnType(this->ui->returnTypeComboBox->currentText());
    this->_meth->setVisibility(this->ui->visibilityComboBox->currentText());

    this->_classItem->appendMeth(this->_meth);

    this->done(QDialog::Accepted);
}

void MethodEditor::cancel()
{
    this->done(QDialog::Rejected);
}

void MethodEditor::setName(QString name)
{
    this->_meth->setText(name);
}

void MethodEditor::setVisibility(int index)
{
    switch(index) {
    default :
        this->_meth->setVisibility("public");
        break;
    case 1 :
        this->_meth->setVisibility("private");
        break;
    case 2:
        this->_meth->setVisibility("protected");
        break;
    }
}

void MethodEditor::setReturnType(QString type)
{
    this->_meth->setReturnType(type);
}

void MethodEditor::setIsAbstract(bool isAbstract)
{
    this->_meth->setIsAbstract(isAbstract);
}

void MethodEditor::addArg()
{
    ClassAttribute *param = new ClassAttribute();
    param->setText(tr("parameter"));
    param->setReturnType("string");
    this->_meth->appendArg(param);
}

void MethodEditor::removeArg()
{
    QItemSelectionModel *selectionModel = this->ui->tableViewArguments->selectionModel();
    QModelIndexList indexes = selectionModel->selectedRows();

    foreach (QModelIndex index, indexes) {
        this->_meth->removeArg(index);
    }
}

void MethodEditor::moveArgUp()
{
    QItemSelectionModel *selectionModel = this->ui->tableViewArguments->selectionModel();
    QModelIndexList indexes = selectionModel->selectedRows();

    foreach (QModelIndex index, indexes) {
        this->_meth->moveArg(index, ClassMethod::MoveUp);
    }
}

void MethodEditor::moveArgDown()
{
    QItemSelectionModel *selectionModel = this->ui->tableViewArguments->selectionModel();
    QModelIndexList indexes = selectionModel->selectedRows();

    foreach (QModelIndex index, indexes) {
        this->_meth->moveArg(index, ClassMethod::MoveDown);
    }
}

void MethodEditor::updatePreview()
{
    this->ui->textEditPreview->setText(this->_meth->umlText());
}
